package com.jeasonzhao.report.model;

import com.jeasonzhao.commons.basic.IntegerPairCollection;
import com.jeasonzhao.commons.basic.StringPairCollection;
import com.jeasonzhao.commons.utils.Algorithms;
import com.jeasonzhao.commons.xml.XMLNode;
import com.jeasonzhao.model.Model;
import com.jeasonzhao.model.ModelException;
import com.jeasonzhao.model.ModelField;
import com.jeasonzhao.report.codes.DataSetCellTypes;
import com.jeasonzhao.report.codes.ReportAlertModels;

@Model("render")
public class ReportAlert extends BaseReportModelItem
{
    private static final long serialVersionUID = 1L;
    public static final String NODE_MODEL = "model";

    @Model("link")
    public static class Link extends ReportAlert
    {
        private static final long serialVersionUID = 1L;
        public Link()
        {
            this.setAlertModel(ReportAlertModels.Href);
        }

        @ModelField(names = "url,link,href,anchor")
        private String m_strURL = null;

        public Link setURL(String str)
        {
            this.m_strURL = str;
            return this;
        }

        public String getURL()
        {
            return m_strURL;
        }

        @ModelField(names = "target")
        private String m_strTarget = null;

        public Link setTarget(String str)
        {
            this.m_strTarget = str;
            return this;
        }

        public String getTarget()
        {
            return m_strTarget;
        }

        public void normalizeModelItem()
            throws ModelException
        {
            super.normalizeModelItem();
            this.setAlertModel(ReportAlertModels.Href);
            if(Algorithms.isEmpty(this.m_strURL))
            {
                throw new ModelException.MissingMandatoryField(this.getClass(),"URL");
            }
        }
    } //ends of class Link

    @Model("report")
    public static class ReportLink extends Link
    {
        private static final long serialVersionUID = 1L;
        public ReportLink()
        {
            this.setAlertModel(ReportAlertModels.Report);
        }

        public void normalizeModelItem()
            throws ModelException
        {
            super.normalizeModelItem();
            this.setAlertModel(ReportAlertModels.Report);
        }
    } //ends of the class ReportLink

    @Model("click")
    public static class ClickEvent extends ReportAlert
    {
        private static final long serialVersionUID = 1L;
        public ClickEvent()
        {
            this.setAlertModel(ReportAlertModels.Click);
        }

        @ModelField(names = "eventHandler,script")
        private String strEventHandler = null;

        public ClickEvent setEventHandlerScript(String str)
        {
            this.strEventHandler = str;
            return this;
        }

        public String getEventHandlerScript()
        {
            return strEventHandler;
        }

        public void normalizeModelItem()
        {
            this.setAlertModel(ReportAlertModels.Click);
        }
    } //ends of class onClick functionality.

    @Model("doubleclick")
    public static class DoubleClickEvent extends ReportAlert
    {
        private static final long serialVersionUID = 1L;
        public DoubleClickEvent()
        {
            this.setAlertModel(ReportAlertModels.DoubleClick);
        }

        public void normalizeModelItem()
        {
            this.setAlertModel(ReportAlertModels.DoubleClick);
        }
    }

    @Model("contextmenu")
    public static class ContextMenuEvent extends ReportAlert
    {
        private static final long serialVersionUID = 1L;
        public ContextMenuEvent()
        {
            this.setAlertModel(ReportAlertModels.ContextMenu);
        }

        public void normalizeModelItem()
        {
            this.setAlertModel(ReportAlertModels.ContextMenu);
        }
    }

    @ModelField(names = "when,expression,where")
    private String m_strExpression = null;

    @ModelField(names = NODE_MODEL)
    private ReportAlertModels m_reportAlertModels = ReportAlertModels.Render;

    @ModelField(names = "cellTypes,cellType,cells")
    private String m_cellTypes = null;

    @ModelField(names = "text,textExpression")
    private String m_textExpression = null;

    @ModelField(names = "rowCss")
    private String m_strCssRow = null;

    @ModelField(names = "cellCss")
    private String m_strCssCell = null;

    @ModelField(names = "param",collection = true)
    protected StringPairCollection m_allParameters = null;

    ///////////////////////////////////////////
    public ReportAlert()
    {
    }

    public ReportAlert(ReportAlert alert)
    {
        super(alert);
        if(null == alert)
        {
            return;
        }
        this.m_strExpression = alert.m_strExpression;
        this.m_reportAlertModels = alert.m_reportAlertModels;
        this.m_cellTypes = alert.m_cellTypes;
        this.m_textExpression = alert.m_textExpression;
    }

    public StringPairCollection getParameters()
    {
        return m_allParameters;
    }

    public String getRenderRowCss()
    {
        return m_strCssRow;
    }

    public String getRenderCellCss()
    {
        return m_strCssCell;
    }

    public String toString()
    {
        return
            this.getAlertModel().toString() + "        " +
            this.getExpression() + "\r\n" +
            "m_strCssRow=" + m_strCssRow + "\r\n" +
            "m_strCssCell=" + m_strCssCell;
    }

    public boolean isMatchCellType(DataSetCellTypes cellType)
    {
        if(null == cellType || null == m_cellTypes)
        {
            return true;
        }
        else
        {
            return m_cellTypes.indexOf("" + cellType.getId()) >= 0;
        }
    }

    public String getExpression()
    {
        return m_strExpression;
    }

    public void setExpression(String Expression)
    {
        this.m_strExpression = Expression;
    }

    public String getTextExpression()
    {
        return m_textExpression;
    }

    public IntegerPairCollection getCellTypesCollection()
    {
        String[] aaa = null == m_cellTypes ? null : m_cellTypes.split(",");
        IntegerPairCollection ret = new IntegerPairCollection();
        for(int n = 0;null != aaa && n < aaa.length;n++)
        {
            DataSetCellTypes a = DataSetCellTypes.fromName(aaa[n]);
            if(null == a || ret.contains(a))
            {
                continue;
            }
            ret.add(a);
        }
        return ret.size() < 1 ? null : ret;
    }

    public String getCellTypes()
    {
        return m_cellTypes;
    }

    public ReportAlertModels getAlertModel()
    {
        return m_reportAlertModels == null ? ReportAlertModels.Render : m_reportAlertModels;
    }

    public void setTextExpression(String textExpression)
    {
        this.m_textExpression = textExpression;
    }

    public void setCellTypes(String cellTypes)
    {
        this.m_cellTypes = cellTypes == null || cellTypes.trim().length() < 1 ? null : cellTypes.trim();
    }

    public void setAlertModel(ReportAlertModels mode)
    {
        this.m_reportAlertModels = mode;
    }

    @SuppressWarnings("unused")
    private String normalizeCellTypesByName(String strCellTypes)
    {
        StringBuffer strn = new StringBuffer();
        if(null != strCellTypes)
        {
            String[] argvs = strCellTypes.split(",");
            for(int n = 0;n < argvs.length;n++)
            {
                strn.append(DataSetCellTypes.fromName(argvs[n]).getId() + ";");
            }
        }
        return strn.toString();
    }

    private static String getCssPart(XMLNode xml,String strXMLAttributeName,String strRealCssPropertyName)
    {
        strRealCssPropertyName = null == strRealCssPropertyName ? strXMLAttributeName : strRealCssPropertyName;
        if(xml.nullValueOf(strXMLAttributeName) == false)
        {
            return strRealCssPropertyName + ":" + xml.valueOf(strXMLAttributeName) + ";";
        }
        else
        {
            return "";
        }
    }

    private static String getCssPart(XMLNode xml,String strXMLAttributeName)
    {
        return getCssPart(xml,strXMLAttributeName,strXMLAttributeName);
    }

    private static String getCssStyles(XMLNode xml)
    {
        if(null == xml)
        {
            return "";
        }
        StringBuffer str = new StringBuffer();
        str.append(getCssPart(xml,"color"));
        str.append(getCssPart(xml,"align","text-align"));
        str.append(getCssPart(xml,"valign","vertical-align"));
        str.append(getCssPart(xml,"width"));
        str.append(getCssPart(xml,"height"));
        str.append(getCssPart(xml,"padding"));
        str.append(getCssPart(xml,"padding-left"));
        str.append(getCssPart(xml,"padding-top"));
        str.append(getCssPart(xml,"padding-right"));
        str.append(getCssPart(xml,"padding-bottom"));
        str.append(getCssPart(xml,"margin"));
        str.append(getCssPart(xml,"margin-left"));
        str.append(getCssPart(xml,"margin-top"));
        str.append(getCssPart(xml,"margin-right"));
        str.append(getCssPart(xml,"margin-bottom"));
        str.append(getCssPart(xml,"border"));
        str.append(getCssPart(xml,"border-left"));
        str.append(getCssPart(xml,"border-top"));
        str.append(getCssPart(xml,"border-right"));
        str.append(getCssPart(xml,"border-bottom"));
        str.append(getCssPart(xml,"font"));
        str.append(getCssPart(xml,"font-weight"));
        str.append(getCssPart(xml,"font-style"));
        str.append(getCssPart(xml,"font-size"));
        str.append(getCssPart(xml,"font-family"));
        str.append(getCssPart(xml,"background"));
        str.append(getCssPart(xml,"text-decoration"));
        str.append(getCssPart(xml,"background-color"));
        if(xml.valueOfBool("bold",false))
        {
            str.append("font-weight:bold;");
        }
        if(xml.valueOfBool("underline",false))
        {
            str.append("text-decoration:underline;");
        }
        if(xml.valueOfBool("line-through",false))
        {
            str.append("text-decoration:line-through;");
        }
        if(xml.nullValueOf("fontsize") == false)
        {
            str.append("font-size:" + xml.valueOf("fontsize") + ";");
        }
        if(xml.nullValueOf("bgcolor","background-color") == false)
        {
            str.append("background-color:" + xml.valueOf("bgcolor","background-color") + ";");
        }
        return str.toString();
    }

    public void afterInitializedFromXML(XMLNode clsItem)
        throws ModelException
    {
        String strCss = getCssStyles(clsItem);
        String strFor = clsItem.valueOf("for");
        String strRowCss = getCssStyles(clsItem.selectNode("row","rowcss","rowStyle"));
        String strCellCss = getCssStyles(clsItem.selectNode("cell","cellcss","cellStyle"));
        strFor = Algorithms.isEmpty(strFor) ? "cell" : strFor;
        if(strFor.equalsIgnoreCase("row"))
        {
            this.m_strCssRow = mergeCss(m_strCssRow,strCss);
        }
        else
        {
            this.m_strCssCell = mergeCss(m_strCssCell,strCss);
        }
        this.m_strCssRow = mergeCss(m_strCssRow,strRowCss);
        this.m_strCssCell = mergeCss(m_strCssCell,strCellCss);
    }

    private String mergeCss(String strInit,String strCss)
    {
        if(Algorithms.isEmpty(strInit))
        {
            return strCss;
        }
        else if(Algorithms.isEmpty(strCss))
        {
            return strInit;
        }
        else
        {
            return strInit + ";" + strCss;
        }
    }

}
